package com.silence.gmall.aop;

import com.alibaba.fastjson2.JSON;
import com.silence.gmall.annotations.Log;
import com.silence.gmall.base.Result;
import com.silence.gmall.enums.CommonCode;
import com.silence.gmall.exception.ServiceException;
import com.silence.gmall.util.AopAndElUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author silence
 * @Email 792245022@qq.com
 * @Date 2025-06-11 14:50
 * @Description 接口注解
 */
@Slf4j
@Aspect
@Component
@Order(Integer.MIN_VALUE)
public class InterfaceControllerAop {

    /**
     * 注解切点
     */
    @Pointcut("@annotation(com.silence.gmall.annotations.Log)")
    public void pointCut() {

    }

    /**
     * 切面逻辑
     *
     * @param point 切点
     * @return 结果
     * @throws Throwable 异常
     */
    @Around(value = "pointCut()")
    public Object doInvoke(ProceedingJoinPoint point) throws Throwable {
        // 获取注解
        Log anLog = AopAndElUtil.getMethodAnnotation(point, Log.class);
        // 没有此注解，继续走逻辑
        if (Objects.isNull(anLog)) {
            return point.proceed();
        }
        // 获取注解上的方法接口名称
        String interfaceName = Optional.ofNullable(anLog.interfaceName()).orElse("");
        log.info("【{}】 - 接口调用开始", interfaceName);
        // 处理入参打印 - 过滤掉MultipartFile
        Object[] args = point.getArgs();
        Object[] loggableArgs = filterNonSerializableArgs(args);
        log.info("【{}】 - 入参打印：{}", interfaceName, JSON.toJSONString(loggableArgs));
        // 计时
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 执行目标方法
        Object result;
        try {
            // 调用目标方法
            result = point.proceed();
            log.info("返回结果：{}", result);
        } catch (ServiceException se) {
            final String errMsg = "【" + interfaceName + "】 - 业务异常";
            log.error(errMsg, se);
            result = Result.build(se.getCode(), se.getMessage());
        } catch (Exception e) {
            final String errMsg = "【" + interfaceName + "】 - 系统异常";
            log.error(errMsg, e);
            result = Result.build(CommonCode.ERROR);
        } finally {
            stopWatch.stop();
            log.info("【{}】 - 耗时：{} ms", interfaceName, stopWatch.getTotalTimeMillis());
        }
        log.info("【{}】 - 接口调用结束", interfaceName);
        log.info("【{}】 - 出参打印：{}", interfaceName, JSON.toJSONString(result));
        return result;
    }

    /**
     * 过滤掉不适合序列化的参数，避免序列化异常
     *
     * @param args 方法参数列表
     * @return 过滤后的参数列表
     */
    private Object[] filterNonSerializableArgs(Object[] args) {
        if (Objects.isNull(args)) {
            return new Object[0];
        }

        Object[] filtered = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            filtered[i] = filterSingleArg(args[i]);
        }
        return filtered;
    }

    /**
     * 过滤单个参数
     *
     * @param arg 单个参数
     * @return 过滤后的参数
     */
    private Object filterSingleArg(Object arg) {
        if (Objects.isNull(arg)) {
            return null;
        }

        switch (arg) {
            // MultipartFile - 文件上传
            case MultipartFile file -> {
                return "MultipartFile{name=" + file.getOriginalFilename() +
                        ", size=" + file.getSize() + ", contentType=" + file.getContentType() + "}";
            }

            // 字节数组 - 二进制数据
            case byte[] bytes -> {
                return "byte[]{length=" + bytes.length + ", hashCode=" + arg.hashCode() + "}";
            }


            // 输入流 - 二进制流
            case InputStream _ -> {
                return "InputStream{type=" + arg.getClass().getSimpleName() + ", hashCode=" + arg.hashCode() + "}";
            }


            // 输出流 - 二进制流
            case OutputStream _ -> {
                return "OutputStream{type=" + arg.getClass().getSimpleName() + ", hashCode=" + arg.hashCode() + "}";
            }


            // HTTP请求和响应对象 - 包含大量不适合序列化的内容
            case HttpServletRequest request -> {
                return "HttpServletRequest{method=" + request.getMethod() +
                        ", uri=" + request.getRequestURI() + "}";
            }
            case HttpServletResponse _ -> {
                return "HttpServletResponse{type=" + arg.getClass().getSimpleName() +
                        ", hashCode=" + arg.hashCode() + "}";
            }
            default -> log.info("不是二进制相关参数");
        }

        // Spring的Resource对象 - 可能包含文件系统引用
        if (arg.getClass().getName().contains("org.springframework.core.io.Resource")) {
            return "Resource{type=" + arg.getClass().getSimpleName() +
                    ", toString=" + arg + "}";
        }

        // 数据库连接对象
        if (arg.getClass().getName().contains("java.sql.Connection") ||
                arg.getClass().getName().contains("javax.sql.DataSource")) {
            return "DatabaseConnection{type=" + arg.getClass().getSimpleName() +
                    ", hashCode=" + arg.hashCode() + "}";
        }

        // 大型集合对象 - 超过一定大小的集合只显示大小
        // 超过100个元素的集合
        if (arg instanceof Collection<?> collection && collection.size() > 100) {
            return "LargeCollection{type=" + arg.getClass().getSimpleName() +
                    ", size=" + collection.size() + "}";
        }

        // 大型Map对象
        // 超过100个元素的Map
        if (arg instanceof java.util.Map<?, ?> map && map.size() > 100) {
            return "LargeMap{type=" + arg.getClass().getSimpleName() +
                    ", size=" + map.size() + "}";
        }

        // 检查是否是循环引用对象或复杂对象
        if (isComplexObject(arg)) {
            return "ComplexObject{type=" + arg.getClass().getSimpleName() +
                    ", hashCode=" + arg.hashCode() + "}";
        }

        // 默认情况：使用安全的JSON序列化
        return trySafeSerialize(arg);
    }

    /**
     * 判断是否是复杂对象（可能包含循环引用或过于复杂）
     *
     * @param obj 对象
     * @return 是否是复杂对象
     */
    private boolean isComplexObject(Object obj) {
        String className = obj.getClass().getName();

        // Spring框架内部对象
        if (className.startsWith("org.springframework.") &&
                !className.contains("data") && // 排除Spring Data的简单对象
                !className.contains("boot.autoconfigure")) {
            return true;
        }

        // Hibernate/JPA代理对象
        if (className.contains("$HibernateProxy$") ||
                className.contains("$_javassist_") ||
                className.contains("CGLIB$$")) {
            return true;
        }

        // 线程相关对象
        return obj instanceof Thread || obj instanceof ThreadLocal;
    }

    /**
     * 尝试安全序列化，如果失败则返回简化信息
     *
     * @param obj 对象
     * @return 序列化后的对象或简化信息
     */
    private Object trySafeSerialize(Object obj) {
        try {
            // 先尝试转换为JSON字符串测试是否可序列化
            JSON.toJSONString(obj);
            return obj; // 如果成功，返回原对象
        } catch (Exception e) {
            // 序列化失败，返回简化信息
            return "NonSerializableObject{type=" + obj.getClass().getSimpleName() +
                    ", hashCode=" + obj.hashCode() +
                    ", error=" + e.getClass().getSimpleName() + "}";
        }
    }

}
